#include "gpio.h"

void GPIO_SetDirection(GPIO_TypeDef *GPIOx, uint32_t pin, GPIOMode mode)
{
    if (mode == GPIO_MODE_OUTPOT)
    {
        GPIOx->DDR |= pin;
    }
    else
    {
        GPIOx->DDR &= ~pin;
    }
}

void GPIO_SetLevel(GPIO_TypeDef *GPIOx, uint32_t pin, GPIOLevel level)
{
    if (level == GPIO_HIGH_LEVEl)
    {
        GPIOx->DR |= pin;
    }
    else
    {
        GPIOx->DR &= ~pin;
    }
}

void GPIO_SetBits(GPIO_TypeDef *GPIOx, uint32_t pin)
{
    GPIOx->DR |= pin;
}

void GPIO_ClearBits(GPIO_TypeDef *GPIOx, uint32_t pin)
{
    GPIOx->DR &= ~pin;
}

void GPIO_InputEnable(GPIO_TypeDef *GPIOx, uint32_t pin)
{
    GPIOx->DDR |= 1<<pin;
}

void GPIO_OutputEnable(GPIO_TypeDef *GPIOx, uint32_t pin)
{
    GPIOx->DDR &= ~pin;
}

void GPIO_IntEnable(GPIO_TypeDef *GPIOx, uint32_t pin)
{
    GPIOx->INTEN |= pin;
}

void GPIO_IntDisable(GPIO_TypeDef *GPIOx, uint32_t pin)
{
    GPIOx->INTEN &= ~pin;
}

void GPIO_SetIntMask(GPIO_TypeDef *GPIOx, uint32_t pin)
{
    GPIOx->INTMASK |= pin;
}

void GPIO_ClrIntMask(GPIO_TypeDef *GPIOx, uint32_t pin)
{
    GPIOx->INTMASK &= ~pin;
}

void GPIO_SetIntType(GPIO_TypeDef *GPIOx, uint32_t pin, GPIOIntrType type)
{
    if (type == GPIO_INTR_ANYEDGE)
    {
        GPIOx->INT_BOTHEDGE |= pin;
        return;
    }

    GPIOx->INT_BOTHEDGE &= ~pin;
    switch (type)
    {
        case GPIO_INTR_LOW_LEVEL:
            GPIOx->INTTYPE_LEVEL &= ~pin;
            GPIOx->INT_POLARITY  &= ~pin;
            break;
        case GPIO_INTR_HIGH_LEVEL:
            GPIOx->INTTYPE_LEVEL &= ~pin;
            GPIOx->INT_POLARITY  |= pin;
            break;
        case GPIO_INTR_NEGEDGE:
            GPIOx->INTTYPE_LEVEL |= pin;
            GPIOx->INT_POLARITY  &= ~pin;
            break;
        case GPIO_INTR_POSEDGE:
            GPIOx->INTTYPE_LEVEL |= pin;
            GPIOx->INT_POLARITY  |= pin;
            break;
        default:
            break;
    }
    
}

uint32_t GPIO_GetIntStatus(GPIO_TypeDef *GPIOx, uint32_t pin)
{
    return GPIOx->INTSTATUS & pin;
}

uint32_t GPIO_GetRawIntStatus(GPIO_TypeDef *GPIOx, uint32_t pin)
{
    return GPIOx->RAW_INTSTATUS & pin;
}

void GPIO_EnableDebounce(GPIO_TypeDef *GPIOx, uint32_t pin)
{
    GPIOx->DEBOUNCE |= pin;
}

void GPIO_DisableDebounce(GPIO_TypeDef *GPIOx, uint32_t pin)
{
    GPIOx->DEBOUNCE &= ~pin;
}

void GPIO_SetEOI(GPIO_TypeDef *GPIOx, uint32_t pin)
{
    GPIOx->EOI |= pin;
}

uint32_t GPIO_GetExt(GPIO_TypeDef *GPIOx, uint32_t pin)
{
    return GPIOx->EXT_PORT & pin;
}